import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:my_flutter_core/my_flutter_core.dart';

class AppUpdateInfo extends StatefulWidget {
  const AppUpdateInfo(this.checkUpdateResult, {super.key});

  final CheckAppUpdateResult checkUpdateResult;

  @override
  State<AppUpdateInfo> createState() => _AppUpdateInfoState();
}

class _AppUpdateInfoState extends State<AppUpdateInfo> {
  late final TapGestureRecognizer _tapGestureRecognizer = TapGestureRecognizer()
    ..onTap = () => openUrl(widget.checkUpdateResult.appInfo!.apkUrl!);

  bool _updateInProgress = false;
  double _downloadProgress = 0;

  @override
  void dispose() {
    _tapGestureRecognizer.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: _onPopInvokedWithResult,
      child: Scaffold(
        appBar: _buildAppBar(),
        body: ListView(
          padding: const EdgeInsets.all(10.0),
          children: _buildListViewContent(),
        ),
      ),
    );
  }

  /// Builds app bar.
  PreferredSizeWidget _buildAppBar() {
    return AppBar(
      title: Text(
        '新版本 ${widget.checkUpdateResult.appInfo!.appVersion} @ ${widget.checkUpdateResult.appInfo!.releaseDate.formatDate(DatePatterns.longDate)}',
      ),
    );
  }

  /// Builds the main content for list view.
  List<Widget> _buildListViewContent() {
    final listViewContent = <Widget>[];

    listViewContent.addAll(_buildChangeLogInfo());
    listViewContent.add(const SizedBox(height: 10.0));

    if (widget.checkUpdateResult.appInfo!.isMandatory!) {
      listViewContent.add(
        Align(
          alignment: Alignment.centerRight,
          child: Container(
            padding: const EdgeInsets.all(3.0),
            color: Colors.orange,
            child: Text(
              '必要更新',
              style: Theme.of(
                context,
              ).textTheme.bodySmall!.copyWith(color: Colors.white),
            ),
          ),
        ),
      );
    }

    listViewContent.add(const Divider());
    listViewContent.add(_buildDownloadWidget());
    listViewContent.add(const SizedBox(height: 10.0));
    listViewContent.add(_buildBrowserDownloadWidget());

    return listViewContent;
  }

  /// Builds the list of widget to display the multi-line change log items.
  List<Widget> _buildChangeLogInfo() {
    return widget.checkUpdateResult.appInfo!.changeLog!
        .split('\\n')
        .map(
          (p) => Container(
            margin: const EdgeInsets.only(bottom: 4.0),
            child: Text(p),
          ),
        )
        .toList();
  }

  /// Builds the widget to display the download progress and button.
  Widget _buildDownloadWidget() {
    return Stack(
      children: [
        if (_updateInProgress)
          Positioned(
            left: 1.0,
            top: 13.0,
            right: 1.0,
            child: MyLinearProgressIndicator(
              value: _downloadProgress,
              height: 30.0,
            ),
          ),
        ListTile(
          title: Text(
            _updateInProgress
                ? '下载 ${(_downloadProgress * 100).toStringAsFixed(0)}%'
                : '立即更新',
            textAlign: TextAlign.center,
            style: TextStyle(
              color: _updateInProgress ? Colors.white : Colors.blue,
            ),
          ),
          onTap: _updateInProgress ? null : _startAppUpdate,
        ),
      ],
    );
  }

  /// Builds the widget to open the browser to download the updated file just in case auto-download does not work.
  Widget _buildBrowserDownloadWidget() {
    return RichText(
      text: TextSpan(
        style: Theme.of(context).textTheme.bodySmall,
        children: <TextSpan>[
          const TextSpan(text: '如点击更新按钮后无反应，请尝试'),
          TextSpan(
            text: ' 打开浏览器下载 ',
            style: Theme.of(
              context,
            ).textTheme.bodySmall!.copyWith(color: Colors.blue),
            recognizer: _tapGestureRecognizer,
          ),
          const TextSpan(text: '。'),
        ],
      ),
    );
  }

  Future<void> _startAppUpdate() async {
    if (PlatformInfo.isAndroid) {
      if (mounted) {
        setState(() => _updateInProgress = true);
      }

      await HttpRequestService().download(
        url: widget.checkUpdateResult.appInfo!.apkUrl!,
        baseDirectory: BaseDirectory.temporary,
        directory: 'family-expense',
        filename: widget.checkUpdateResult.appInfo!.apkFilename!,
        openFileOnComplete: true,
        onProgress: (p) {
          if (mounted) {
            setState(() => _downloadProgress = p);
          }
        },
        onFailed: () {
          showConfirmDialog(
            context,
            '自动下载失败，是否用浏览器下载？',
            onConfirm: () {
              openUrl(widget.checkUpdateResult.appInfo!.apkUrl!);
            },
          );
        },
      );

      if (mounted) {
        setState(() {
          _downloadProgress = 0;
          _updateInProgress = false;
        });
      }
    } else {
      showToast('请前往App Store进行更新');
    }
  }

  /// Checks the data before popping.
  void _onPopInvokedWithResult(bool didPop, dynamic result) {
    if (didPop) {
      return;
    }

    if (_updateInProgress) {
      showToast('下载在后台继续，完成后会自动提示。');
    }

    NavigatorHelper.pop(context);
  }
}
